using System;
using System.Collections.Specialized;
using System.Data;
using System.Web.UI;
using System.Web.UI.WebControls;
using Sedna.Core.Common.Objects.Navigation;
using Sedna.Core.Controller;
using Sedna.Core.Controller.Configurations;
using Sedna.Core.Controls.Grid;
using Sedna.Core.Controls.Support;
using ControlBuilder=Sedna.Core.Controls.Support.ControlBuilder;

namespace Sedna.Core.Controls.Template
{
	public class ItemColumnTemplate : ITemplate
	{
		protected DataGrid dataGrid;
		protected IDataGridColumnConfiguration columnConfiguration;


		public ItemColumnTemplate(DataGrid dataGrid, IDataGridColumnConfiguration columnConfiguration)
		{
			this.dataGrid = dataGrid;
			this.columnConfiguration = columnConfiguration;
		}

		public virtual void InstantiateIn(Control container)
		{
			//TODO: we might want to set up cell size explicitely. in this case column configuration should be extended with the Width and Hight properties support
			if (container is WebControl)
			{
//				((WebControl)container).Width = (columnConfiguration.Width.IsEmpty ? Unit.Percentage(0) : columnConfiguration.Width);
				//We don't want columns with absent width to be 0%
			    ((WebControl)container).Width = columnConfiguration.Width;
			}

			if (columnConfiguration.ControlConfiguration != null)
			{
                if (columnConfiguration.Width.IsEmpty)
                {
                    ((WebControl)container).Width = Unit.Percentage(0);                    
                }
                Control innerControl = ControlBuilder.BuildControl(columnConfiguration.ControlConfiguration);
                //PENDING: the view state of IDataGridAwareControl is need for track bound entities
				innerControl.EnableViewState = ((innerControl is IDataGridAwareControl) || columnConfiguration.CommandName != null || columnConfiguration.CommandArgumentsGenerator != null);
				
				if ((innerControl is IDataGridAwareControl) && dataGrid.Controller != null)
				{
					((IDataGridAwareControl)innerControl).Controller = dataGrid.Controller;
				}
				
				innerControl.DataBinding += new EventHandler(this.BindControl);
				container.Controls.Add(innerControl);
			}
			else
			{
			    System.Web.UI.WebControls.Label label = new System.Web.UI.WebControls.Label();				
				label.EnableViewState = false;				
				label.DataBinding += new EventHandler(this.BindLabel);
				container.Controls.Add(label);
			}			
		}

		protected virtual void BindLabel(object sender, EventArgs args)
		{
			System.Web.UI.WebControls.Label label = (System.Web.UI.WebControls.Label)sender;
			DataGridItem dataGridItem = (DataGridItem)label.NamingContainer;

			Object value = columnConfiguration.DataTranslator.Translate(label, GetValue(dataGridItem.DataItem));
			label.Text = (value != null ? value.ToString() : String.Empty);

			label.Enabled = columnConfiguration.IsEnabledForPrincipal();
            if (dataGrid.Controller != null && dataGrid.Controller.InvalidData != null && dataGrid.Controller.InvalidData != null && dataGrid.Controller.InvalidData.Contains(dataGridItem.DataItem))
            {
                dataGridItem.CssClass = "innertablecellinvalid";
            }
		}

		protected virtual void BindControl(Object sender, EventArgs args)
		{				
			DataGridItem dataGridItem = (DataGridItem)((Control)sender).NamingContainer;

			if (sender is ICommandAware)
			{
				ICommandAware commandAware = (ICommandAware)sender;

				if(columnConfiguration.CommandArgumentsGenerator != null)
				{
					commandAware.CommandArgument = columnConfiguration.CommandArgumentsGenerator.GenerateCommandArguments(columnConfiguration, dataGridItem, ExecutionContext.Current);
				}
				else
				{
					commandAware.CommandArgument = GetStringValue(dataGridItem.DataItem);
				}
				
				if (columnConfiguration.CommandName != null)
				{
					commandAware.CommandName = columnConfiguration.CommandName;					
				}

				String clickFormat = (columnConfiguration.CommandName != null && columnConfiguration.OnClick == null ? 
					String.Format("{0}({1}'{{0}}')", columnConfiguration.CommandName, (columnConfiguration.IncludeSource ? "this," : String.Empty)) : 
					columnConfiguration.OnClick);					

				if (clickFormat!=null)
				{
					commandAware.OnClick = String.Format(clickFormat, commandAware.CommandArgument);
				}
			}

			if(columnConfiguration.DataTranslator != null)
			{
				columnConfiguration.DataTranslator.Translate(sender as Control, GetValue(dataGridItem.DataItem));
			}

			if (sender is IDataGridAwareControl)
			{
				((IDataGridAwareControl)sender).OnDataBinding(dataGridItem);
                if (dataGrid.Controller != null && dataGrid.Controller.InvalidData != null && dataGrid.Controller.InvalidData.Contains(dataGridItem.DataItem))
                {
                    dataGridItem.CssClass = "innertablecellinvalid";
                }
            }

		    if (columnConfiguration.ControlConfigurator!=null)
		    {
                columnConfiguration.ControlConfigurator.Configure((Control)sender, columnConfiguration, dataGridItem.DataItem, ExecutionContext.Current);   
		    }
		    
			((WebControl)sender).Enabled = (columnConfiguration.IsEnabledForPrincipal() && columnConfiguration.ColumnControlEnabler.CheckIfEnabled(columnConfiguration, dataGridItem.DataItem, ExecutionContext.Current));
            ((WebControl)sender).Visible = (columnConfiguration.IsVisibleForPrincipal() && columnConfiguration.ColumnControlEnabler.CheckIfVisible(columnConfiguration, dataGridItem.DataItem, ExecutionContext.Current));
		}

		private String GetStringValue(Object dataItem)
		{
			Object result = GetValue(dataItem);

			return (result == null ? String.Empty : result.ToString());
		}

		private Object GetValue(Object dataItem)
		{
			if (columnConfiguration.DataField != null)
			{
				if (dataItem is NameValueCollection)
				{
					return ((NameValueCollection)dataItem)[columnConfiguration.DataField];
				}

				if ((dataItem is DataRowView) && ((DataRowView)dataItem).Row.Table.Columns.Contains(columnConfiguration.DataField))
				{
					return ((DataRowView)dataItem)[columnConfiguration.DataField];
				}
				else if (dataItem is DataRowView)
				{
					return null;
				}

                try
                {
                    return ScopePathParser.Instance.Parse(dataItem, columnConfiguration.DataField).Value;
                }
			    catch (Exception)
			    {
                    return null;
			    }
			}

			return null;
		}		
	}
}
